﻿namespace Arms.Framework.Validators
{
    using System;

    public class Validation
    {
        /// <summary>
        /// Delegates to a supplied action if condition is met.
        /// </summary>
        /// <param name="conditionIsMet">Determines whether the condition is met</param>
        /// <param name="actionIfConditionIsMet">Delegate action if condition is met</param>
        public static void Requires(bool conditionIsMet, Action actionIfConditionIsMet)
        {
            if (conditionIsMet)
            {
                actionIfConditionIsMet();
            }
        }
        /// <summary>
        /// Delegates to a supplied action if condition is met.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="conditionIsMet">Determines whether the condition is met</param>
        /// <param name="throwIfConditionIsNotMet">Determines whether to throw error if the condition is not met</param>
        /// <param name="message">Exception message</param>
        /// <param name="actionIfConditionIsMet">Delegate action if condition is met</param>
        public static void Requires<T>(bool conditionIsMet, bool throwIfConditionIsNotMet, string message, Action actionIfConditionIsMet) where T : Exception
        {
            if (throwIfConditionIsNotMet)
            {
                Validation.Requires<T>(conditionIsMet, message);
            }

            Validation.Requires(conditionIsMet, actionIfConditionIsMet);
        }
        /// <summary>
        /// Throws an exception with message if condition is met
        /// </summary>
        /// <typeparam name="T">Type of exception</typeparam>
        /// <param name="conditionIsMet">Exception is thrown if this value is false</param>
        /// <param name="message">Exception message</param>
        public static void Requires<T>(bool conditionIsMet, string message) where T : Exception
        {
            if (!conditionIsMet)
            {
                throw (T)Activator.CreateInstance(typeof(T), message);
            }
        }
        /// <summary>
        /// Throws an ArgumentNullException if the source object is null
        /// </summary>
        /// <param name="source">Object to validate</param>
        /// <param name="message">Exception message</param>
        public static void Ensure(object source, string message)
        {
            Validation.Requires<ArgumentNullException>(source != null, message);
        }
        /// <summary>
        /// Throws an ArgumentNullException if the source object is null.
        /// Returns the object otherwise.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public static T Ensure<T>(T source, string message)
        {
            if (source == null)
            {
                throw new ArgumentNullException(message);
            }
            else
            {
                return source;
            }
        }
        /// <summary>
        /// Throws an ArgumentNullException if the source object is null.
        /// Returns the object otherwise.
        /// Exception message is defaulted to the source object's full runtime type name.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static T Ensure<T>(T source)
        {
            return Validation.Ensure<T>(source, source.GetRunTimeType().FullName);
        }
    }
}
